﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Configuration;
using NPMonitor.DataModel;
using NPMonitor.Configuration;

namespace NPMonitor.Implementation
{
    public sealed class FileManager
    {
        #region Properties

        public static string UploadFolderPath
        {
            get
            {
                string uploadFolderPath = ConfigurationManager.AppSettings["UploadFolder"];

                uploadFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, uploadFolderPath);

                return uploadFolderPath;
            }
        }

        public static string UploadFolderTempPath
        {
            get
            {
                return Path.Combine(UploadFolderPath, "_temp");
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// check file existence, download it if not exists
        /// </summary>
        /// <param name="fileData"></param>
        /// <returns></returns>
        public static bool Download(JobDefinition jobDefinition, Func<DownloadSettings, string, bool> onDownloadSuccess = null)
        {
            string jobFolder = Path.Combine(
                Configuration.ConfigurationSettings.SettingsProvider.JobExecutionFolder,
                Configuration.ConfigurationSettings.SettingsProvider.JobFileFolder);

            string downloadUrl = Configuration.ConfigurationSettings.SettingsProvider.JobFileDownloadUrl
                + "?filename=" + jobDefinition.FileName + "&id=" + jobDefinition.JobId;

            DownloadSettings downloadSetting = new DownloadSettings(jobFolder);

            downloadSetting.AddDownload(downloadUrl, jobDefinition.FileName);

            Download(downloadSetting, onDownloadSuccess);

            return true;
        }

        public static bool Download(DownloadSettings downloadSetting, Func<DownloadSettings, string, bool> onDownloadSuccess = null)
        {
            string storeFolder = downloadSetting.GetStoreFolder();

            if (!Directory.Exists(storeFolder))
            {
                Directory.CreateDirectory(storeFolder);
            }

            foreach (DownloadObject obj in downloadSetting.Objects)
            {
                WebClient client = new WebClient();
                client.UseDefaultCredentials = true;
                // client.Proxy = new WebProxy("135.251.33.16");
                // client.Proxy.Credentials = new NetworkCredential("ad4\\zzhao007", "eka2012#");

                byte[] data = client.DownloadData(obj.Url);

                if (data.Length > 0)
                {
                    string filePath = downloadSetting.GetStoreFilePath(obj);

                    using (FileStream fs = new FileStream(filePath, FileMode.Create))
                    {
                        fs.Write(data, 0, data.Length);
                    }

                    if (onDownloadSuccess != null)
                    {
                        onDownloadSuccess.Invoke(downloadSetting, filePath);
                    }
                }
                else
                {
                    throw new Exception("Download job file " + obj.SaveName + " failed.");
                }
            }

            return true;
        }

        public static bool DeleteUploadedTempFile(string tmpFileName)
        {
            string filePath = GetUploadedTempFilePath(tmpFileName);

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            return true;
        }

        public static bool DeleteUploadedFile(string fileName)
        {
            string filePath = GetUploadedFilePath(fileName);

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            return true;
        }

        public static string SaveAsTempFile(HttpPostedFile postedFile)
        {
            string fileName = postedFile.FileName;
            string tmpFileName = GetUploadedTempFileName(fileName);

            string tmpFilePath = Path.Combine(UploadFolderTempPath, tmpFileName);

            string fileExtension = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf("."));

            //check the file extension
            if (fileExtension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase)
                || fileExtension.Equals(".exe", StringComparison.InvariantCultureIgnoreCase))
            {
                if (!Directory.Exists(UploadFolderTempPath))
                {
                    Directory.CreateDirectory(UploadFolderTempPath);
                }

                if (File.Exists(tmpFilePath))
                {
                    File.Delete(tmpFilePath);
                }

                //save file to temp path
                postedFile.SaveAs(tmpFilePath);
            }

            return tmpFilePath;
        }

        public static string SaveUploadedFileByTempFile(string tmpFileName)
        {
            if (!Directory.Exists(UploadFolderPath))
            {
                Directory.CreateDirectory(UploadFolderPath);
            }

            string fileName = GetUploadedFileNameByTempFileName(tmpFileName);
            string filePath = GetUploadedFilePath(fileName);

            string tmpFilePath = GetUploadedTempFilePath(tmpFileName);

            File.Copy(tmpFilePath, filePath, true);
            File.Delete(tmpFilePath);   // Delete temporary file after save success.

            return filePath;
        }

        #endregion

        #region 内部方法

        internal static string GetDownloadedJobFilePath(string fileName)
        {
            string folderPath = Configuration.ConfigurationSettings.SettingsProvider.JobExecutionFolder;

            return folderPath;
        }

        /// <summary>
        /// Retrieve absolute temporary file path by file name
        /// </summary>
        /// <param name="tmpFileName"></param>
        /// <returns></returns>
        internal static string GetUploadedTempFilePath(string tmpFileName)
        {
            string filePath = Path.Combine(UploadFolderTempPath, tmpFileName);

            return filePath;
        }

        /// <summary>
        /// Retrieve absolute file path by file name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        internal static string GetUploadedFilePath(string fileName)
        {
            string filePath = Path.Combine(UploadFolderPath, fileName);

            return filePath;
        }

        /// <summary>
        /// Get temporary file name by file name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        internal static string GetUploadedTempFileName(string fileName)
        {
            string tmpFileName = String.Format("{0}_{1}", Guid.NewGuid().ToString(), fileName);

            return tmpFileName;
        }

        /// <summary>
        /// Get uploaded file name by temporary file name
        /// </summary>
        /// <param name="tmpFileName"></param>
        /// <returns></returns>
        internal static string GetUploadedFileNameByTempFileName(string tmpFileName)
        {
            string fileName = tmpFileName;
            fileName = tmpFileName.Substring(tmpFileName.IndexOf('_') + 1);

            return fileName;
        }

        #endregion
    }
}
